/*
 * =====================================================================================
 *
 *       Filename:  lander.cpp
 *
 *    Description:  
 *
 *        Version:  1.0
 *        Created:  22.01.2010 12:03:54
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Michal Antonczak (uzyszkodnik), uzyszkodnik.priv@gmail.com
 *        Company:  
 *
 * =====================================================================================
 */
#include 	"lander.h"
#include	"particles.h"
#include	"gamestructs.h"
#include	"sdlstuff.h"
#include	<SDL/SDL.h>
#include	<SDL/SDL_rotozoom.h>
#include	<SDL/SDL_ttf.h>

using namespace std;

Lander::Lander(SDL_Surface* scr,SDL_Surface* cm, struct physic_consts* p, struct ship* si,struct position_i* mi){

	collision_map=cm;	
	ship_info = si;
	phys = p;
	map_info = mi;

	if((img = load_img("lander.png"))==NULL)
		sdlimgerror("loading lander object");	

	Uint32 colorkey = SDL_MapRGB( img->format, 0,0xFF, 0xFF);
	SDL_SetColorKey(img, SDL_SRCCOLORKEY, colorkey);


	position_int.x=ship_info->start_x;
	position_int.y=ship_info->start_y;
	
	position_float.x=position_int.x;
	position_float.y=position_int.y;

	momentum.setval(0,0);

	engine_force.setval(0,0);

	//angle=0;

	// need to change way of the physic engine init

	if((font = TTF_OpenFont( "font.ttf", 12 ))==NULL){

		printf("ttf init: %s", TTF_GetError());
		exit(1);

	}
	textColor = {0,0xFF,0};

//	c_timer.start();
	angle = 0;

	state =1;	
	
	lander_tmp=NULL;
	communicate=NULL;
	pengine = new ParticleEngine(scr,collision_map);
	pengine->dispersion = 3.14/6;
}
Lander::~Lander(){
	SDL_FreeSurface(img);
	SDL_FreeSurface(lander_tmp);
	SDL_FreeSurface(communicate);
	TTF_CloseFont(font);
	delete pengine;

}
void Lander::rotate(){

	if(lander_tmp!=NULL){
		SDL_FreeSurface(lander_tmp);
		lander_tmp=NULL;
	}

	double degreeangle = angle*180.0f/3.14;
	lander_tmp=rotozoomSurface(img, degreeangle,1,0);

	Uint32 colorkey = SDL_MapRGB( lander_tmp->format, 0,0xFF, 0xFF);
	SDL_SetColorKey(lander_tmp, SDL_SRCCOLORKEY, colorkey);


}
void Lander::hud(){
	int locked=0;

	Uint32 colorkey ;

	if(communicate!=NULL)
		SDL_FreeSurface(communicate);
	
	double mass=ship_info->ship_mass+ship_info->fuel_mass;
	char comm[512];
	int x,y;
	SDL_Surface *speed_com, *speed_angle_com, *fuel_com, *engine_com;

	Wektor v;
	v=momentum/mass;

	sprintf(comm,"speed: %.2f", v.value);
	speed_com = TTF_RenderText_Solid(font, comm, textColor);

	sprintf(comm,"speed angle: %.2f", v.angle);
	speed_angle_com =  TTF_RenderText_Solid(font, comm, textColor);

	sprintf(comm, "fuel: %.2f %%", (ship_info->fuel_mass/ship_info->max_fuel_mass)*100.0f);
	fuel_com =  TTF_RenderText_Solid(font, comm, textColor);

	sprintf(comm, "engine usage: %.2f %%", (fabs(engine_force.value) / ship_info->engine_max_power)*100.0f);
	engine_com = TTF_RenderText_Solid(font, comm, textColor);

	x = engine_com->w;
	y = speed_com->h + speed_angle_com->h + fuel_com -> h + engine_com->h;

	SDL_Rect pos;	
	communicate = SDL_CreateRGBSurface(SDL_HWSURFACE,x, y,32, 0x00, 0x00,0x00,0);
	SDL_Rect fillme;

	fillme.x=0;
	fillme.y=0;
	fillme.w = x;
	fillme.h= y;

	colorkey = SDL_MapRGB( communicate->format, 0,0xFF, 0xFF);

	SDL_FillRect(communicate, &fillme, colorkey);


	pos.x = 0;
	pos.y = 0; 
	SDL_BlitSurface(speed_com, NULL, communicate, &pos);
	pos.y+=speed_com->h;
	SDL_BlitSurface(speed_angle_com, NULL, communicate, &pos);
	pos.y+=speed_angle_com->h;
	SDL_BlitSurface(fuel_com, NULL, communicate, &pos);
	pos.y+=fuel_com->h;
	SDL_BlitSurface(engine_com, NULL, communicate, &pos);

	SDL_SetColorKey(communicate, SDL_SRCCOLORKEY, colorkey);

	SDL_FreeSurface(speed_com);
	SDL_FreeSurface(speed_angle_com);
	SDL_FreeSurface(fuel_com);
	SDL_FreeSurface(engine_com);

}
void Lander::frame(){

	rotate();
	calculatepos();
	calculate_fuel_usage();
	//collision detected, ship is down	
	hud();
	collision();
	//if we've successfully landed
	//else if(landed())
	//	state=2;
}
/*
void Lander::show(){

		calculatepos();

//		if(collision())
//			puts("kolizja");	
//		else
//			puts("brak");
		
		calculate_fuel_usage();
		SDL_BlitSurface( lander_tmp ,NULL, screen, &position_int );
		SDL_FreeSurface(lander_tmp);
}
*/
void Lander::calculatepos(){
#define DEBUG(DEBUGME, NAME)  printf("%s, x:%f, y:%f, value:%f, angle:%f\n",NAME,DEBUGME.x, DEBUGME.y, DEBUGME.value, DEBUGME.angle)

	Wektor Fw;
	Wektor momentumw, accelw, momentumtmp;
	//Wektor accelt;
	Wektor move;
	double mass;
	mass = ship_info->ship_mass+ship_info->fuel_mass;
	//float time_left =(float)c_timer.tslc()/1000;
	double time_left = FRAME_TIME/1000;

	Fw = engine_force+phys->gravity*mass;
	momentumw = Fw * time_left;

	momentumtmp = momentum + momentumw;
	
	//fw acceleration
	accelw.setval(Fw.value/mass, Fw.angle);

	// atmosphere accel
	//accelt.setval(phys->rub/mass,momentumtmp.angle-3.14); 	

	v = momentum/mass;

//	dv = ( accelw + accelt )*time_left+v;

	dv = ( accelw )*time_left+v;
	/*
	if(v.value<dv.value){
		v.setval(0,momentum.angle);
		dv=v;
	}
	*/

	move = ( (v+dv)/2)*time_left;	
	position_float.x+=move.x;
	position_float.y+=move.y;



	momentum =  momentumtmp;
	
	if(position_float.x<0)
		position_float.x=0;
	if(position_float.y<0)
		position_float.y=0;	

	if(position_float.x>(map_info->x-lander_tmp->w))
		position_float.x=map_info->x-lander_tmp->w;

	if(position_float.y>(map_info->y-lander_tmp->h))
		position_float.y=map_info->y-lander_tmp->h;

	position_int.x=(int)position_float.x;
	position_int.y=(int)position_float.y;		
	
	// if engine was used we'll calculate it's position to nicely emit the particles
	
	Wektor particlesv;
	if(engine_force.value < 0){

		float tmpx, tmpy;
		float alfa = angle*(-1);
		float maxparticlespeed = 30;
		float maxparticlesnum = 50;
		float prop = fabs((float)engine_force.value)/(float)ship_info->engine_max_power;
		tmpx = 0;
		tmpy  = img->h/2;

		engine_position.x = tmpx*cos(alfa)-tmpy*sin(alfa) + position_int.x + img->w/2 ;
		engine_position.y = tmpx*sin(alfa)+tmpy*cos(alfa)+ position_int.y + img->h/2;

		particlesv.setval(prop*maxparticlespeed, engine_force.angle);

		pengine->emit(prop*maxparticlesnum,engine_position.x, engine_position.y, particlesv);
			
	}
}

void Lander::collision(){

	Uint32 space_color= SDL_MapRGB(collision_map->format, 0, 0, 0);
	Uint32 mask_color= SDL_MapRGB(lander_tmp->format, 0,0xFF,0xFF);
	Uint32 landing_pad_color = SDL_MapRGB(collision_map->format, 0xFF,0,0);
	
	Uint32 *bg_color, *lander_color;
	Uint32 bg_offset, lander_offset;

	Wektor v;

	bool landed = false;
	int i,j;
	
	bool collock=false, shiplock=false;

	if(SDL_MUSTLOCK(collision_map)){
		SDL_LockSurface(collision_map);
		collock = true;
	}

	if(SDL_MUSTLOCK(lander_tmp)){
		shiplock=true;
		SDL_LockSurface(lander_tmp);
	}
 	v=momentum/(ship_info->ship_mass+ship_info->fuel_mass);

	//can we safely land?	
	if((fabs(angle)/2<=ship_info->safe_landing_angle)&&(v.x<=ship_info->safe_landing_speed.x)&&(v.y<=ship_info->safe_landing_speed.y) ){

		for(i=0;i<lander_tmp->w;i++){

			bg_color = (Uint32 *)(collision_map->pixels+(lander_tmp->h+position_int.y)*collision_map->pitch+(i+position_int.x)*collision_map->format->BytesPerPixel);
			lander_color =	(Uint32 *)(lander_tmp->pixels+(lander_tmp->h)*lander_tmp->pitch+i*lander_tmp->format->BytesPerPixel);

			//have we landed?
			if( (*lander_color!=mask_color ) && (*bg_color==landing_pad_color) )
				landed=true;

			if( (*lander_color!=mask_color) && (*bg_color!=space_color) && (*bg_color != landing_pad_color))
				landed=false;
			
		}		

		if(landed){
			state=SHIP_LANDED;
			goto ret;
		}
	}

	for(i=0;i<lander_tmp->h;i++)

		for(j=0;j<lander_tmp->w;j++){

			bg_color = (Uint32 *)(collision_map->pixels+(i+position_int.y)*collision_map->pitch+(j+position_int.x)*collision_map->format->BytesPerPixel);
			lander_color =	(Uint32 *)(lander_tmp->pixels+i*lander_tmp->pitch+j*lander_tmp->format->BytesPerPixel);

			//calculation of the pixel address
		//	bg_offset =  (i+position_int.y)*collision_map->pitch+(j+position_int.x)*collision_map->format->BytesPerPixel;
		//	lander_offset = i*lander_tmp->pitch+j*lander_tmp->format->BytesPerPixel ;

			//pixels comparison
			//bg_color = (Uint32 *)((Uint32)collision_map->pixels+bg_offset);
			//lander_color = (Uint32 *)((Uint32)lander_tmp->pixels+lander_offset);

			//are we fucked?
			if( ( *bg_color  != space_color ) && ( *lander_color  != mask_color ) ){
				state=SHIP_CRASHED;
				goto ret;
				//yes we are
			}
	}
	//still alive
	state=SHIP_OK;
	ret:
	if(shiplock){
		shiplock=false;
		SDL_UnlockSurface(lander_tmp);
	}	
	if(collock){
		collock=false;
		SDL_UnlockSurface(collision_map);
	}
	return;
}

void Lander::incengine(){

	if(ship_info->fuel_mass<=0){
		stopengine();
		return;

	}

	if(fabs(engine_force.value-ship_info->engine_inc*FRAME_TIME/1000) >= ship_info->engine_max_power)
		engine_force.setval(ship_info->engine_max_power*(-1), angle);
	else
		engine_force.setval(engine_force.value-ship_info->engine_inc*FRAME_TIME/1000, angle); 
}

void Lander::stopengine(){
	engine_force.setval(0, angle);
}

void Lander::rotate_right(){
	angle+=ship_info->rotation_speed*FRAME_TIME/1000;
	while(angle>7)
		angle-=6.28;
	engine_force.setval(engine_force.value, angle);

}

void Lander::rotate_left(){
	angle-=ship_info->rotation_speed*FRAME_TIME/1000;
	while(angle<-7)
		angle += 6.28;
	engine_force.setval(engine_force.value, angle);
}

void Lander::calculate_fuel_usage(){
	if(engine_force.value<0)
		ship_info->fuel_mass-=ship_info->fuel_usage*fabs(engine_force.value)*FRAME_TIME/1000;
	if(ship_info->fuel_mass<0)
		ship_info->fuel_mass=0;
}

